home *** CD-ROM | disk | FTP | other *** search
/ World of Video / World of Video.iso / gfxprograms / 3dprograms / t3dlib / source / writeps.c < prev    next >
C/C++ Source or Header  |  1995-02-13  |  9KB  |  293 lines

  1. /* writeps.c - routines to output PostScript representation of object
  2.  *           - using TTDDDLIB by Glenn M. Lewis - 7/23/91
  3.  */
  4.  
  5. static char rcs_id[] = "$Id: writeps.c,v 1.18 1993/01/30 12:55:49 glewis Exp $";
  6.  
  7. #include <stdio.h>
  8. #include "t3dlib.h"
  9. #ifdef __STDC__
  10. #include <stdlib.h>
  11. #include <strings.h>
  12. #include "writeps_protos.h"
  13. #endif
  14.  
  15. double XSIZE = 8.5;
  16. double YSIZE = 11.0;
  17. #define EXTRASPACE 0.95
  18. #define MARGIN    (0.25)    /* On each side of the page */
  19. #define PPI    (72.0)
  20. #define COS60    (0.5)
  21. #define COS30    (0.8660)
  22.  
  23. static void write_PS_header();
  24. static void draw_PS_view();
  25. static void render_PS_object();
  26.  
  27. static FILE *out;
  28. static WORLD *world;
  29. static MBB mbb;
  30. static double xsize, ysize;
  31. static int view;
  32. static double xoffset, yoffset, scale, ybottom;
  33.  
  34. void calculate_MBB_world(world)
  35. WORLD *world;
  36. {
  37.     register OBJECT *obj;
  38.  
  39.     if (!world) return;
  40.  
  41.     /* Determine the extent of the world object */
  42.     mbb.minx = mbb.miny = mbb.minz =  1.0e10;
  43.     mbb.maxx = mbb.maxy = mbb.maxz = -1.0e10;
  44.     for (obj=world->object; obj; obj=obj->next) {
  45.         calculate_MBB(obj);
  46.         if (!obj->user) continue;
  47.         if (((MBB*)obj->user)->minx<mbb.minx) mbb.minx=((MBB*)obj->user)->minx;
  48.         if (((MBB*)obj->user)->miny<mbb.miny) mbb.miny=((MBB*)obj->user)->miny;
  49.         if (((MBB*)obj->user)->minz<mbb.minz) mbb.minz=((MBB*)obj->user)->minz;
  50.         if (((MBB*)obj->user)->maxx>mbb.maxx) mbb.maxx=((MBB*)obj->user)->maxx;
  51.         if (((MBB*)obj->user)->maxy>mbb.maxy) mbb.maxy=((MBB*)obj->user)->maxy;
  52.         if (((MBB*)obj->user)->maxz>mbb.maxz) mbb.maxz=((MBB*)obj->user)->maxz;
  53.     }
  54.     world->user = (void*)&mbb;
  55. }
  56.  
  57. int write_PostScript(object, file, selected_view)
  58. WORLD *object;
  59. FILE *file;
  60. int selected_view;
  61. {
  62.     double llx, lly;
  63.     if (!(out = file)) return(0);        /* File not open */
  64.     if (!(world = object)) return(0);    /* No object */
  65.  
  66.     calculate_MBB_world(world);
  67.  
  68. #ifdef DEBUG
  69.     fprintf(stderr, "MBB: (%.12g,%.12g,%.12g)-(%.12g,%.12g,%.12g)\n",
  70.         mbb.minx, mbb.miny, mbb.minz,
  71.         mbb.maxx, mbb.maxy, mbb.maxz);
  72. #endif
  73.  
  74.     write_PS_header();
  75.     if (selected_view==VIEW_ALL_FOUR) {
  76.         for (view=0; view<4; view++) {
  77.             llx = ((view&0x02) ? XSIZE/2.0 : MARGIN) * PPI;
  78.             lly = ((view&0x01) ? MARGIN : YSIZE/2.0) * PPI;
  79.             xsize = PPI*(XSIZE/2.0 - MARGIN);
  80.             ysize = PPI*(YSIZE/2.0 - MARGIN);
  81.             fprintf(out, "gsave\n0.1 setlinewidth\n%.12g %.12g translate\n", llx, lly);
  82.             draw_PS_view();
  83.             fprintf(out, "grestore\n");
  84.         }
  85.     } else {
  86.         xsize = PPI*(XSIZE - 2.0*MARGIN);
  87.         ysize = PPI*(YSIZE - 2.0*MARGIN);
  88.         fprintf(out,"0.1 setlinewidth\n%.12g %.12g translate\n",PPI*MARGIN,PPI*MARGIN);
  89.         view=selected_view;
  90.         draw_PS_view();
  91.     }
  92.     fprintf(out, "showpage\n");
  93.     return(1);
  94. }
  95.  
  96. void calculate_MBB(obj)
  97. OBJECT *obj;
  98. {
  99.     OBJECT *child;
  100.     register XYZ_st *p;
  101.     register int i;
  102.     MBB *mbb;
  103.     double x, y, z;
  104.  
  105.     if (!obj) return;
  106.     if (!obj->desc && !obj->child) return;    /* Not an object */
  107.     if (obj->user) { free((char*)obj->user); obj->user=0; }
  108.  
  109.     if (!(mbb = (MBB*)malloc(sizeof(MBB)))) {
  110.         fputs("Out of memory", out); exit(-1); }
  111.     mbb->minx = mbb->miny = mbb->minz =  1.0e10;
  112.     mbb->maxx = mbb->maxy = mbb->maxz = -1.0e10;
  113.  
  114.     /* Account for children... */
  115.     for (child=obj->child; child; child=child->next) {
  116.         calculate_MBB(child);
  117.         if (!child->user) continue;
  118.         if (((MBB*)child->user)->minx < mbb->minx)
  119.             mbb->minx = ((MBB*)child->user)->minx;
  120.         if (((MBB*)child->user)->miny < mbb->miny)
  121.             mbb->miny = ((MBB*)child->user)->miny;
  122.         if (((MBB*)child->user)->minz < mbb->minz)
  123.             mbb->minz = ((MBB*)child->user)->minz;
  124.         if (((MBB*)child->user)->maxx > mbb->maxx)
  125.             mbb->maxx = ((MBB*)child->user)->maxx;
  126.         if (((MBB*)child->user)->maxy > mbb->maxy)
  127.             mbb->maxy = ((MBB*)child->user)->maxy;
  128.         if (((MBB*)child->user)->maxz > mbb->maxz)
  129.             mbb->maxz = ((MBB*)child->user)->maxz;
  130.     }
  131.  
  132.     x = y = z = 0.0;
  133. /*
  134.     if (obj->desc->posi) {
  135.         x = obj->desc->posi->x;
  136.         y = obj->desc->posi->y;
  137.         z = obj->desc->posi->z;
  138.         fprintf(out, "position: %lx (%.12g,%.12g,%.12g)\n", (unsigned long)obj,x,y,z);
  139.     }
  140. */
  141.     for (p=obj->desc->pnts,i=obj->desc->pcount; i--; p++) {
  142.         if (p->x-x < mbb->minx) mbb->minx = p->x-x;
  143.         if (p->y-y < mbb->miny) mbb->miny = p->y-y;
  144.         if (p->z-z < mbb->minz) mbb->minz = p->z-z;
  145.         if (p->x-x > mbb->maxx) mbb->maxx = p->x-x;
  146.         if (p->y-y > mbb->maxy) mbb->maxy = p->y-y;
  147.         if (p->z-z > mbb->maxz) mbb->maxz = p->z-z;
  148.     }
  149.     obj->user = (void *)mbb;
  150. #ifdef DEBUG
  151.     fprintf(stderr, "MBB: %lx child:%lx next:%lx (%.12g,%.12g,%.12g)-(%.12g,%.12g,%.12g)\n",
  152.         (unsigned long)obj,
  153.         (unsigned long)obj->child,
  154.         (unsigned long)obj->next,
  155.         mbb->minx, mbb->miny, mbb->minz,
  156.         mbb->maxx, mbb->maxy, mbb->maxz);
  157. #endif
  158. }
  159.  
  160. static void write_PS_header()
  161. {
  162.     fputs("%! PS-Adobe-2.0 EPSF-1.2\n", out);
  163.     fprintf(out, "%%%%BoundingBox: %.12g %.12g %.12g %.12g\n",
  164.         PPI*MARGIN, PPI*MARGIN, PPI*(XSIZE-2.0*MARGIN), PPI*(YSIZE-2.0*MARGIN));
  165.     fputs("%%Creator: TTDDDLIB by Glenn M. Lewis\n", out);
  166.     fputs("%%EndComments\n%%BeginSetup\n", out);
  167.     fputs("/M {moveto} bind def\n", out);
  168.     fputs("/D {lineto} bind def\n", out);
  169.     fputs("/S {stroke} bind def\n", out);
  170.     fputs("%%EndSetup\n", out);
  171. }
  172.  
  173. static void draw_PS_view()
  174. {
  175.     double xratio, yratio, zratio;
  176.     OBJECT *obj;
  177.     fprintf(out, "0 0 M %.12g 0 D %.12g %.12g D 0 %.12g D 0 0 D S\n",
  178.         xsize, xsize, ysize, ysize);
  179.  
  180.     if (mbb.maxx-mbb.minx>0.0) xratio=1.0/(mbb.maxx-mbb.minx); else xratio=1.0;
  181.     if (mbb.maxy-mbb.miny>0.0) yratio=1.0/(mbb.maxy-mbb.miny); else yratio=1.0;
  182.     if (mbb.maxz-mbb.minz>0.0) zratio=1.0/(mbb.maxz-mbb.minz); else zratio=1.0;
  183.     scale = (ysize*yratio < xsize*yratio ? ysize*yratio : xsize*yratio);
  184.     scale = (scale        < ysize*zratio ? scale        : ysize*zratio);
  185.     scale = (scale        < xsize*xratio ? scale        : xsize*xratio);
  186.     /* Scale makes it fit exactly into the area.  Expand it a little */
  187.     scale *= EXTRASPACE;
  188.  
  189.     switch(view) {
  190.         case VIEW_TOP:
  191.             fputs("% Top view\n", out);
  192.             xoffset = (xsize-scale/xratio)/2.0;
  193.             yoffset = (ysize-scale/yratio)/2.0;
  194.             break;
  195.         case VIEW_FRONT:
  196.             fputs("% Front view\n", out);
  197.             xoffset = (xsize-scale/xratio)/2.0;
  198.             yoffset = (ysize-scale/zratio)/2.0;
  199.             break;
  200.         case VIEW_ISO:
  201.             fputs("% Isometric view\n", out);
  202.             xratio = (mbb.maxx-mbb.minx)*COS30+(mbb.maxy-mbb.miny)*COS30;
  203.             if (xratio>0.0) xratio = 1.0/xratio; else xratio=1.0;
  204.             ybottom = -(mbb.maxx-mbb.minx)*COS60;
  205.             yratio = (mbb.maxz-mbb.minz)+(mbb.maxy-mbb.miny)*COS60    /* Top */
  206.                      - ybottom;
  207.             if (yratio>0.0) yratio = 1.0/yratio; else yratio=1.0;
  208.             scale = (xsize*xratio < ysize*yratio ? xsize*xratio : ysize*yratio);
  209.             scale *= EXTRASPACE;
  210.             xoffset = (xsize-scale/xratio)/2.0;
  211.             yoffset = (ysize-scale/yratio)/2.0;
  212.             break;
  213.         case VIEW_RIGHT:
  214.             fputs("% Right view\n", out);
  215.             xoffset = (xsize-scale/yratio)/2.0;
  216.             yoffset = (ysize-scale/zratio)/2.0;
  217.             break;
  218.     }
  219.     for (obj=world->object; obj; obj=obj->next)
  220.         render_PS_object(obj);
  221. }
  222.  
  223. static void render_PS_object(obj)
  224. register OBJECT *obj;
  225. {
  226.     register UWORD *f;
  227.     register OBJECT *op;
  228.     register int i, j;
  229.     int p[3];
  230.     double x[3], y[3];
  231.  
  232.     if (!obj->desc) return;
  233.     for (op=obj->child; op; op=op->next)    /* render children first */
  234.         render_PS_object(op);
  235.     
  236.     /* Now, the meat... */
  237. #if 0
  238.     if (obj->desc->shap && obj->desc->shap[1]!=0) return;    /* A lamp */
  239. #endif
  240.     if (!obj->desc->edge || !obj->desc->pnts || !obj->desc->face) return;
  241.     for (f=obj->desc->face,i=obj->desc->fcount; i--; f+=3) {
  242.         p[0] = obj->desc->edge[((*f)<<1)];
  243.         p[1] = obj->desc->edge[((*f)<<1)+1];
  244.         if (obj->desc->edge[((f[1])<<1)] == p[0] ||
  245.             obj->desc->edge[((f[1])<<1)] == p[1])
  246.             p[2] = obj->desc->edge[((f[1])<<1)+1];
  247.         else
  248.             p[2] = obj->desc->edge[((f[1])<<1)];
  249.         switch(view) {
  250.             case VIEW_TOP:
  251.                 for (j=3; j--; ) {
  252.                     x[j] = obj->desc->pnts[p[j]].x-mbb.minx;
  253.                     y[j] = obj->desc->pnts[p[j]].y-mbb.miny;
  254.                 }
  255.                 break;
  256.             case VIEW_FRONT:
  257.                 for (j=3; j--; ) {
  258.                     x[j] = obj->desc->pnts[p[j]].x-mbb.minx;
  259.                     y[j] = obj->desc->pnts[p[j]].z-mbb.minz;
  260.                 }
  261.                 break;
  262.             case VIEW_ISO:
  263.                 for (j=3; j--; ) {
  264.                     x[j] = (obj->desc->pnts[p[j]].x-mbb.minx)*COS30
  265.                           +(obj->desc->pnts[p[j]].y-mbb.miny)*COS30;
  266.                     y[j] = (obj->desc->pnts[p[j]].z-mbb.minz)
  267.                           -(obj->desc->pnts[p[j]].x-mbb.minx)*COS60
  268.                           +(obj->desc->pnts[p[j]].y-mbb.miny)*COS60
  269.                           - ybottom;
  270.                 }
  271.                 break;
  272.             case VIEW_RIGHT:
  273.                 for (j=3; j--; ) {
  274.                     x[j] = obj->desc->pnts[p[j]].y-mbb.miny;
  275.                     y[j] = obj->desc->pnts[p[j]].z-mbb.minz;
  276.                 }
  277.                 break;
  278.         }
  279.         if (x[0]==x[1] && x[1]==x[2] && y[0]==y[1] && y[1]==y[2]) continue;
  280.         fprintf(out, "%0.2lf %0.2lf M ", xoffset+scale*x[0],yoffset+scale*y[0]);
  281.         if (!(x[0]==x[1] && y[0]==y[1])) {
  282.             fprintf(out, "%0.2lf %0.2lf D ",
  283.                 xoffset+scale*x[1], yoffset+scale*y[1]);
  284.         }
  285.         if (!(x[0]==x[2] && y[0]==y[2]) && !(x[1]==x[2] && y[1]==y[2])) {
  286.             fprintf(out, "%0.2lf %0.2lf D ",
  287.                 xoffset+scale*x[2], yoffset+scale*y[2]);
  288.         }
  289.         fprintf(out, "%0.2lf %0.2lf D S\n",
  290.             xoffset+scale*x[0],yoffset+scale*y[0]);
  291.     }
  292. }
  293.